﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Xml;
using MassIntellect.WorkIt;
using System.Xml.Linq;

namespace MassIntellect
{
	/// <summary>
	/// Xml-коммутатор
	/// </summary>
	/// <typeparam name="T">Селектор принимаемых</typeparam>
	/// <typeparam name="P">Селектор каналов</typeparam>
	public class XmlSwitch<T, P> : WorkFrame
		where T : IXmlSelector, new()
		where P : IXmlPipeSelector, new()
	{
		[Serialize]
		public string ContentKey { get; set; }

		[Serialize(IgnoreDefault = true)]
		[Description("Объединять элементы в группы при отсылке")]
		public bool MergeSignal { get; set; }

		protected string GetContentKey()
		{
			return ContentKey.IsEmpty() ? "Content" : ContentKey;
		}

		public override IEnumerable<IPipe> Pipes
		{
			get
			{
				yield return this;
				foreach (var item in GetPipeSelector().Pipes)
					yield return item;
			}
		}		

		protected override void protectedPulse(PulseArgs args)
		{
			XElement xe;
			PulseArgs a2;
			IPipe pipe;
			string cntkey = GetContentKey();
			if (args.ContainsKey(cntkey)
				&& (xe = args[cntkey] as XElement) != null)
			{
				GetXmlSelector();
				GetPipeSelector();
				foreach (var item in XmlSelector.Select(xe))
				{
					a2 = args.Clone();
					a2[cntkey] = item;
					//Echo("Селектор Xml {0} > {1}", xe.Name.LocalName, item.Name.LocalName);
					pipe = PipeSelector.Select(item);
					//Echo("Коммутатор Xml {0} > {1}", item.Name.LocalName, pipe.Name);
					if (pipe != this)
						pipe.Pulse(a2);
					else
						ThroughPulse(a2);
				}
			}
		}

		protected IXmlSelector GetXmlSelector()
		{
			return XmlSelector ?? (XmlSelector = new T { Owner = this });
		}

		protected IXmlPipeSelector GetPipeSelector()
		{
			return PipeSelector ?? (PipeSelector = new P { Owner = this });
		}

		protected IXmlSelector XmlSelector;
		protected IXmlPipeSelector PipeSelector;

		public override void SetUp(XElement xe)
		{
			base.SetUp(xe);
			XElement sx;
			if ((sx = xe.Element("XmlSelector")) != null)
			{
				GetXmlSelector();
				XmlSerializeProvider.SetUp(XmlSelector, sx);
			}
			if ((sx = xe.Element("PipeSelector")) != null)
			{
				GetPipeSelector();
				XmlSerializeProvider.SetUp(PipeSelector, sx);
			}
		}

		public override XElement Serialize()
		{
			XElement sx = base.Serialize();
			if (XmlSelector != null)
				sx.Add(XmlSerializeProvider.Serialize(XmlSelector, "XmlSelector"));
			if (PipeSelector != null)
				sx.Add(XmlSerializeProvider.Serialize(PipeSelector, "PipeSelector"));
			return sx;
		}
	}
}
